package com.taomeishu.mailcrazy.util;

/**
 * @author pister 2012-4-1 下午08:09:52
 */
public class NumberUtil {
	
	final static char[] digits = {
		'0' , '1' , '2' , '3' , '4' , '5' ,
		'6' , '7' , '8' , '9' , 'a' , 'b' ,
		'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
		'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
		'o' , 'p' , 'q' , 'r' , 's' , 't' ,
		'u' , 'v' , 'w' , 'x' , 'y' , 'z' ,
		'A' , 'B' ,	'C' , 'D' , 'E' , 'F' , 
		'G' , 'H' ,	'I' , 'J' , 'K' , 'L' , 
		'M' , 'N' ,	'O' , 'P' , 'Q' , 'R' , 
		'S' , 'T' ,	'U' , 'V' , 'W' , 'X' , 
		'Y' , 'Z' , '-' , '_',  '.'
	    };
	
	final static int MAX_RADIX = digits.length;
	
	final static int MIN_RADIX = 2;
	
	private static final long MULTMIN_RADIX_TEN = Long.MIN_VALUE / 10;
	private static final long N_MULTMAX_RADIX_TEN = -Long.MAX_VALUE / 10;
	
	final static int[] chars = new int[128];
	
	static {
		for (int i = 0; i <= 9; ++i) {
			chars['0' + i] = i;
		}
		for (int i = 0; i <= 26; ++i) {
			chars['a' + i] = 10 + i;
		}
		for (int i = 0; i <= 26; ++i) {
			chars['A' + i] = 36 + i;
		}
		
		chars['-'] = 62;
		chars['_'] = 63;
		chars['.'] = 64;
	}
	
	
	public static String formatLong65(long i) {
		return formatLong(i, 65);
	}
	
	public static String formatLong64(long i) {
		return formatLong(i, 64);
	}
	
	public static String formatLong62(long i) {
		return formatLong(i, 62);
	}
	
	public static long parseLong62(String s) {
		return parseLong(s, 62);
	}
	
	public static String formatLong(long i, int radix) {
		if (radix < MIN_RADIX || radix > MAX_RADIX)
			radix = 10;
		if (radix == 10)
			return Long.toString(i);
		char[] buf = new char[65];
		int charPos = 64;
		boolean negative = (i < 0);

		if (!negative) {
			i = -i;
		}

		while (i <= -radix) {
			buf[charPos--] = digits[(int) (-(i % radix))];
			i = i / radix;
		}
		buf[charPos] = digits[(int) (-i)];

		if (negative) {
			buf[--charPos] = '-';
		}
		return new String(buf, charPos, (65 - charPos));
	}
	
	public static long parseLong(String s, int radix) {
		if (s == null) {
			throw new NumberFormatException("null");
		}

		if (radix < MIN_RADIX) {
			throw new NumberFormatException("radix " + radix + " less " + MIN_RADIX);
		}
		if (radix > MAX_RADIX) {
			throw new NumberFormatException("radix " + radix + " greater than " + MAX_RADIX);
		}

		long result = 0;
		boolean negative = false;
		int i = 0, max = s.length();
		long limit;
		long multmin;
		int digit;

		if (max > 0) {
			if (s.charAt(0) == '-') {
				negative = true;
				limit = Long.MIN_VALUE;
				i++;
			} else {
				limit = -Long.MAX_VALUE;
			}
			if (radix == 10) {
				multmin = negative ? MULTMIN_RADIX_TEN : N_MULTMAX_RADIX_TEN;
			} else {
				multmin = limit / radix;
			}
			if (i < max) {
				char c = s.charAt(i++);
				digit = chars[c];
				if (digit < 0) {
					throw new NumberFormatException(s);
				} else {
					result = -digit;
				}
			}
			while (i < max) {
				// Accumulating negatively avoids surprises near MAX_VALUE
				char c = s.charAt(i++);
				digit = chars[c];
				if (digit < 0) {
					throw new NumberFormatException(s);
				}
				if (result < multmin) {
					throw new NumberFormatException(s);
				}
				result *= radix;
				if (result < limit + digit) {
					throw new NumberFormatException(s);
				}
				result -= digit;
			}
		} else {
			throw new NumberFormatException(s);
		}
		if (negative) {
			if (i > 1) {
				return result;
			} else { /* Only got "-" */
				throw new NumberFormatException(s);
			}
		} else {
			return -result;
		}
	}
	
	
}
